package com.yzion.baselib.fragment

import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.FloatRange
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import androidx.viewbinding.ViewBinding
import com.blankj.utilcode.util.ActivityUtils
import com.blankj.utilcode.util.BusUtils
import com.blankj.utilcode.util.FragmentUtils
import com.blankj.utilcode.util.KeyboardUtils
import com.blankj.utilcode.util.ScreenUtils
import com.blankj.utilcode.util.ThreadUtils
import com.weikaiyun.fragmentation.ExtraTransaction
import com.weikaiyun.fragmentation.ISupportActivity
import com.weikaiyun.fragmentation.ISupportFragment
import com.weikaiyun.fragmentation.SupportFragmentDelegate
import com.weikaiyun.fragmentation.SwipeBackLayout
import com.weikaiyun.fragmentation_swipeback.core.ISwipeBackFragment
import com.weikaiyun.fragmentation_swipeback.core.SwipeBackFragmentDelegate
import com.yzion.baselib.R
import com.yzion.baselib.activity.BaseActivity
import com.yzion.baselib.dialog.BaseLoadingDialog
import com.yzion.baselib.app.IAppProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel

/**
 * 默认样式的DialogFragment，弹窗
 */
abstract class BaseDialogFragment<VB : ViewBinding> :
    DialogFragment(), ISwipeBackFragment, ISupportFragment {

    val supportFragmentDelegate by lazy { SupportFragmentDelegate(this) }
    val swipeBackFragmentDelegate by lazy { SwipeBackFragmentDelegate(this) }

    var baseLoadingDialog: BaseLoadingDialog? = null
    lateinit var bind: VB

    var onDismiss: (() -> Unit)? = null

    open fun isSwipeBackEnable() = false

    /**
     * 实例化对应的ViewBinding
     */
    abstract fun getViewBinding(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): VB

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        supportFragmentDelegate.onViewCreated(savedInstanceState)
        swipeBackFragmentDelegate.onViewCreated(view, savedInstanceState)

        baseLoadingDialog =
            (requireContext().applicationContext as IAppProvider).createLoadingDialog(requireContext()) as BaseLoadingDialog
        setSwipeBackEnable(isSwipeBackEnable())//默认是false
        if (dialog != null) {
            dialog!!.setCanceledOnTouchOutside(true)
        }
        initView()
        BusUtils.register(this)
        initData()
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        bind = getViewBinding(inflater, container, savedInstanceState)
        return attachToSwipeBack(bind.root)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        supportFragmentDelegate.onCreate(savedInstanceState)
        swipeBackFragmentDelegate.onCreate(savedInstanceState)
        setStyle(STYLE_NO_TITLE, R.style.CustomDialog)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        BusUtils.unregister(this)
        hideSoftInput()
        onDismiss?.invoke()
        lifecycleScope.cancel()
    }

    fun hideSoftInput() {
        runCatching {
            if (KeyboardUtils.isSoftInputVisible(requireActivity())) KeyboardUtils.hideSoftInput(
                requireActivity()
            )
        }
    }

    protected abstract fun initView()

    abstract fun initData()

    fun showLoading(text: String? = null): BaseLoadingDialog? {
        ThreadUtils.runOnUiThread {
            try {
                baseLoadingDialog?.setLoadingTip(text)?.show()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        return baseLoadingDialog
    }

    fun hideLoading() {
        ThreadUtils.runOnUiThread {
            try {
                baseLoadingDialog?.dismiss()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    fun show(): Boolean {
        try {
            if (isVisible) return false
            if (ActivityUtils.getTopActivity() is BaseActivity) {
                val a = ActivityUtils.getTopActivity() as BaseActivity
                show(a.supportFragmentManager, getTagName())
                return true
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return false
    }

    override fun dismiss() {
        if (isDestroy().not()) {
            runCatching {
                dismissAllowingStateLoss()
            }
        }
    }

    override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)
    }

    open fun getTagName(): String {
        return this.hashCode().toString()
    }

    fun getBaseActivity(): BaseActivity? {
        try {
            if (activity is BaseActivity) {
                return activity as BaseActivity
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return null
    }

    fun isDestroy(): Boolean {
        return isRemoving || isDetached
    }

    override fun getSupportDelegate(): SupportFragmentDelegate {
        return supportFragmentDelegate
    }

    override fun extraTransaction(): ExtraTransaction {
        return supportFragmentDelegate.extraTransaction()
    }

    override fun post(p0: Runnable?) {

    }

    override fun lazyInit() {

    }

    override fun setFragmentResult(p0: Int, p1: Bundle?) {

    }

    override fun onFragmentResult(p0: Int, p1: Int, p2: Bundle?) {

    }

    override fun onNewBundle(p0: Bundle?) {

    }

    override fun putNewBundle(p0: Bundle?) {

    }

    override fun onBackPressedSupport(): Boolean {
        return supportFragmentDelegate.onBackPressedSupport()
    }

    override fun onVisible() {

    }

    override fun onInvisible() {

    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        runCatching {
            supportFragmentDelegate.onAttach(context)
        }
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        supportFragmentDelegate.onSaveInstanceState(outState)
    }


    override fun attachToSwipeBack(view: View?): View {
        return swipeBackFragmentDelegate.attachToSwipeBack(view)
    }

    override fun getSwipeBackLayout(): SwipeBackLayout {
        return swipeBackFragmentDelegate.swipeBackLayout
    }

    override fun setSwipeBackEnable(enable: Boolean) {
        swipeBackFragmentDelegate.setSwipeBackEnable(enable)
    }

    override fun setEdgeLevel(edgeLevel: SwipeBackLayout.EdgeLevel?) {
        swipeBackFragmentDelegate.setEdgeLevel(edgeLevel)
    }

    override fun setEdgeLevel(widthPixel: Int) {
        swipeBackFragmentDelegate.setEdgeLevel(widthPixel)
    }

    override fun setParallaxOffset(@FloatRange(from = 0.0, to = 1.0) offset: Float) {
        swipeBackFragmentDelegate.setParallaxOffset(offset)
    }

}